// Tossim Batch mode
// by Mina Jung @ syracuse university
// April 2010


#import "TossimBatchSwarm.h"
#import "TossimModelSwarm.h"
#import <simtools.h> // ObjectLoader
#import <analysis.h> // EZGraph

#include <misc.h> // printf

@implementation TossimBatchSwarm

// createBegin: here we set up the default observation parameters.

+ createBegin:  aZone 
{
  TossimBatchSwarm *obj;

  // Superclass createBegin to allocate ourselves.
  obj = [super createBegin: aZone];

  // Fill in the relevant parameters.
  obj->loggingFrequency = 1;
  obj->experimentDuration = 250;

  return obj;
}

- buildObjects
{
  [super buildObjects];

  if ((tossimModelSwarm = [lispAppArchiver getWithZone: self 
                                            key: "modelSwarm"]) == nil)
    raiseEvent(InvalidOperation, 
               "Can't find the parameters to create modelSwarm");

  // Now, let the model swarm build its objects.
  [tossimModelSwarm buildObjects];

  if(loggingFrequency)
    {
      batteryGraph = [EZGraph createBegin: self];
      [batteryGraph setGraphics: 0] ;
      [batteryGraph setFileOutput: 1] ;
      batteryGraph = [batteryGraph createEnd] ;
      
      [batteryGraph createAverageSequence: "battery.output"
                    withFeedFrom: [tossimModelSwarm getTossimList] 
                    andSelector: M(getAmtBattery)] ;
    }
  // All done - we're ready to build a schedule and go.
  return self;
}  

// Create the actions necessary for the simulation. This is where
// the schedule is built (but not run!)

- buildActions 
{
  [super buildActions];
  
  // First, let our model swarm build its own schedule.

  [tossimModelSwarm buildActions];
  
  if(loggingFrequency)
    {
      
      displayActions = [ActionGroup create: self];
      
      [displayActions createActionTo: batteryGraph message: M(step)];
      
      displaySchedule = [Schedule createBegin: self];
      [displaySchedule setRepeatInterval: loggingFrequency];
      displaySchedule = [displaySchedule createEnd];
      
      [displaySchedule at: 0 createAction: displayActions];
    }
  
  
  stopSchedule = [Schedule create: self];
  [stopSchedule at: experimentDuration 
                createActionTo: self 
                message: M(stopRunning)];
  
  return self;
}  

// activateIn: - get the Swarm ready to run.
- (id <Activity>)activateIn:  swarmContext 
{
  [super activateIn: swarmContext];
  
  [tossimModelSwarm activateIn: self];
  
  [stopSchedule activateIn: self];
  if (loggingFrequency)
    [displaySchedule activateIn: self];
  
  return [self getActivity];
}

// the TossimObserverSwarm had a go method inherited from GUISwarm,
// but we have to define our own here. It's pretty simple. There's also
// a friendly message printed out here just in case someone is confused
// when they run tossim and see no graphics.

- go 
{
  printf ("You typed `tossim -b' or `tossim --batch', so we're running without graphics.\n");

  printf ("Tossims is running for %d timesteps.\n",experimentDuration) ;
 
  if (loggingFrequency)
    printf ("It is logging data every %d timesteps to: battery.output.\n",
            loggingFrequency);
  
  [[self getActivity] run];
  return [[self getActivity] getStatus];
}

// And the termination method. When this fires we just terminate everything
// that's running and close our output file(s) by dropping the EZGraph which
// "owns" the sequence(s) we are logging.

- stopRunning 
{
  [getTopLevelActivity() terminate]; // Terminate the simulation.

  if(loggingFrequency)
    [batteryGraph drop] ;              // Close the output file.

  return self;
}

@end
